﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Web;
using Shinkansen.Model;
using Shinkansen.Core;

namespace Shinkansen.Runtime
{
    public class HeaderSetup
    {
        private readonly HttpContext _context;
        private readonly ResourceInformation _resourceInfo;

        /// <summary>
        /// Initializes a new instance of the <see cref="HeaderSetup"/> class.
        /// </summary>
        /// <param name="context">The context.</param>
        /// <param name="resourceInfo">The resource info.</param>
        public HeaderSetup (HttpContext context, ResourceInformation resourceInfo)
        {
            _context = context;
            _resourceInfo = resourceInfo;
        }

        /// <summary>
        /// Sets the response headers.
        /// </summary>
        public void SetContentTypeHeader ()
        {
            string ct;

            switch (_resourceInfo.ResourceType)
            {
                case ResourceType.Css:          ct = "text/css"; break;
                case ResourceType.JavaScript:   ct = "text/javascript"; break;
                case ResourceType.Image:        ct = GetImageMimeType (_resourceInfo.Paths); break;

                default:
                    throw new InvalidOperationException (string.Format ("Unsupported resource type '{0}'.", _resourceInfo.ResourceType));
            }

            _context.Response.ContentType = ct;
        }

        /// <summary>
        /// Gets the type of the image MIME.
        /// </summary>
        /// <param name="paths">The paths.</param>
        /// <returns></returns>
        private string GetImageMimeType (IEnumerable<string> paths)
        {
            string path = paths.FirstOrDefault ();

            if (string.IsNullOrEmpty (path))
                throw new InvalidOperationException ("No image path specified.");

            string extension = Path.GetExtension (path).Trim ('.');
            return string.Format ("image/{0}", extension);
        }

        /// <summary>
        /// Sets the content encoding header.
        /// </summary>
        public void SetContentEncodingHeader ()
        {
            switch (_resourceInfo.CompressionMode)
            {
                case HttpCompressionMode.Deflate:
                    _context.Response.AppendHeader ("Content-Encoding", "deflate");
                    break;

                case HttpCompressionMode.GZip:
                    _context.Response.AppendHeader ("Content-Encoding", "gzip");
                    break;
            }
        }

        /// <summary>
        /// Sets the caching headers.
        /// </summary>
        public void SetCachingHeaders ()
        {
            TimeSpan duration = TimeSpan.FromDays (365);
            HttpCachePolicy cache = _context.Response.Cache;
 
            cache.SetCacheability (HttpCacheability.Public);
            cache.SetExpires (DateTime.Now.Add (duration));
            cache.SetMaxAge (duration);

            cache.AppendCacheExtension ("must-revalidate, proxy-revalidate");
        }
    }
}